using System;
using JetBrains.Annotations;
using UnityEngine;

namespace com.susi.util.toolkit
{
    public static class ObservableExtension
    {
        /// <summary>
        /// DebugLogNotice on every observable message.
        /// </summary>
        public static IDisposable Subscribe<T>(this IObservable<T> observable, IObserver<T> observer,
            string DEBUGPrefix)
        {
            return new LocalUnityDebugObserver<T>(observable, observer, DEBUGPrefix);
        }

        private class LocalUnityDebugObserver<T> : IObserver<T>, IDisposable
        {
            private string Prefix;
            private IObservable<T> Observable;
            private IObserver<T> Observer;
            private IDisposable Unsubscribe;

            public LocalUnityDebugObserver([NotNull] IObservable<T> observable,
                [NotNull] IObserver<T> observer, [NotNull] string prefix)
            {
                Prefix = prefix ?? throw new ArgumentNullException(nameof(prefix));
                Observable = observable ?? throw new ArgumentNullException(nameof(observable));
                Observer = observer ?? throw new ArgumentNullException(nameof(observer));
                Unsubscribe = Observable.Subscribe(this);
            }

            public void OnCompleted()
            {
                Debug.Log($"[notice][LocalUnityDebugObserver][{Prefix}]Completed");
                Observer.OnCompleted();
            }

            public void OnError(Exception error)
            {
                Debug.Log($"[notice][LocalUnityDebugObserver][{Prefix}]{error}:{error.Message}");
                Observer.OnError(error);
            }

            public void OnNext(T value)
            {
                Debug.Log($"[notice][LocalUnityDebugObserver][{Prefix}]OnNext:{value}");
                Observer.OnNext(value);
            }

            public void Dispose()
            {
                Unsubscribe.Dispose();
                Unsubscribe = null;
                Prefix = null;
                Observable = null;
                Observer = null;
            }
        }
        
        
    }
}